/*
* IBlas.cs
* 
* This provides our interface to BLAS routines.
* 
* Copyright (c) 2005, dnAnalytics. All rights reserved.
*/

#region Using Directives
using dnAnalytics.Math;
#endregion

namespace dnAnalytics.LinearAlgebra.Native
{
    /// <summary>
    /// An enumeration of the available BLAS providers.
    /// </summary>
    public enum BlasProvider
    {
        /// <summary>
        /// Provider for AMD's ACML.
        /// </summary>
        Acml,

        /// <summary>
        /// Provider for the ATLAS library.
        /// </summary>
        Atlas,

        /// <summary>
        /// Provider for INTEL's Math Kernel Library.
        /// </summary>
        Mkl
    }

    /// <summary>
    /// The matrix data storage format.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1008:EnumsShouldHaveZeroValue")]
    internal enum BlasOrderType
    {
        /// <summary>
        /// The matrix array uses a row-major layout.
        /// </summary>
        Row = 101,

        /// <summary>
        /// The matrix array uses a column-major layout.
        /// </summary>
        Column = 102
    }

    /// <summary>
    /// DenseMatrix transpose type.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1008:EnumsShouldHaveZeroValue")]
    internal enum BlasTransType
    {
        /// <summary>
        /// Don't transpose the matrix.
        /// </summary>
        NoTrans = 111,

        /// <summary>
        /// Transpose the matrix.
        /// </summary>
        Trans = 112,

        /// <summary>
        /// Conjugate transpose the matrix. The only refers to complex matrices. Real matrices will just be transposed.
        /// </summary>
        ConjTrans = 113
    }

    /// <summary>
    /// Triangular matrix type.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1008:EnumsShouldHaveZeroValue")]
    internal enum BlasUpLoType
    {
        /// <summary>
        /// Data is stored in the upper triangle of the matrix.
        /// </summary>
        Upper = 121,

        /// <summary>
        /// Data is stored in the lower triangle of the matrix.
        /// </summary>
        Lower = 122
    }

    /// <summary>
    /// Specifies whether a matrix is unit triangular.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1008:EnumsShouldHaveZeroValue")]
    internal enum BlasDiagType
    {
        /// <summary>
        /// The matrix is not unit triangular.
        /// </summary>
        NonUnit = 131,

        /// <summary>
        /// The matrix is unit triangular.
        /// </summary>
        Unit = 132
    }

    /// <summary>
    /// DenseMatrix side to apply an operation. 
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1008:EnumsShouldHaveZeroValue")]
    internal enum BlasSideType
    {
        /// <summary>
        /// Left side of the matrix.
        /// </summary>
        Left = 141,

        /// <summary>
        /// Right side of the matrix.
        /// </summary>
        Right = 142
    }

    /// <summary>
    /// Interface for BLAS routines.
    /// </summary>
    internal interface IBlas
    {
        #region BLAS1 Routines

        /// <summary>
        /// Computes a vector-vector dot product.
        /// </summary>
        /// <param name="n">The order of the vectors.</param>
        /// <param name="x">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        /// <returns>The dot product if <paramref name="n"/> &gt; 0, 0 otherwise.</returns>
        double Ddot(int n, double[] x, int incX, double[] y, int incY);

        /// <summary>
        /// Computes a vector-vector dot product.
        /// </summary>
        /// <param name="n">The order of the vectors.</param>
        /// <param name="x">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        /// <returns>The dot product if <paramref name="n"/> &gt; 0, 0 otherwise.</returns>
        Complex Zdotu_sub(int n, Complex[] x, int incX, Complex[] y, int incY);

        /// <summary>
        /// Computes the dot product of conjugated vector with another vector.
        /// </summary>
        /// <param name="n">The order of the vectors.</param>
        /// <param name="x">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        /// <returns>The dot product if <paramref name="n"/> &gt; 0, 0 otherwise.</returns>
        Complex Zdotc_sub(int n, Complex[] x, int incX, Complex[] y, int incY);

        /// <summary>
        /// Computes the Euclidean norm of a vector.
        /// </summary>
        /// <param name="n">order of the vector.</param>
        /// <param name="x">vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <returns>the Euclidean norm.</returns>
        double Dnrm2(int n, double[] x, int incX);

        /// <summary>
        /// Calculate the sum of magnitudes of the vector elements.
        /// </summary>
        /// <param name="n">The order of <paramref name="x"/>.</param>
        /// <param name="x">The vector to sum with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <returns>The sum of magnitudes of the vector elements</returns>
        double Dasum(int n, double[] x, int incX);

        /// <summary>
        /// Computes the Euclidean norm of a vector.
        /// </summary>
        /// <param name="n">The order of the vector.</param>
        /// <param name="x">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <returns>the Euclidean norm.</returns>
        double Dznrm2(int n, Complex[] x, int incX);

        /// <summary>
        /// Calculate the sum of magnitudes of the vector elements (the magnitude of if the real part plus the magnitude of the imaginary part).
        /// </summary>
        /// <param name="n">The order of <paramref name="x"/>.</param>
        /// <param name="x">A vector to sum with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <returns>sum of magnitudes of the vector elements</returns>
        double Dzasum(int n, Complex[] x, int incX);

        /// <summary>
        /// Returns the position of the element with the largest absolute value.
        /// </summary>
        /// <param name="n">The order of the vector.</param>
        /// <param name="x">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <returns>The position of the element with the largest absolute value.</returns>
        int Idamax(int n, double[] x, int incX);

        /// <summary>
        /// Returns the position of the element with the largest sum of the absolute value of the real component
        /// the absolute value of the imaginary part.
        /// </summary>
        /// <param name="n">The order of the vector.</param>
        /// <param name="x">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <returns>the position of the element with the largest sum of the absolute value of the real component
        /// the absolute value of the imaginary part.</returns>
        int Izamax(int n, Complex[] x, int incX);

        /// <summary>
        /// Swaps the values of one vector with another vector.
        /// </summary>
        /// <param name="n">The order of the vectors.</param>
        /// <param name="x">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        void Dswap(int n, double[] x, int incX, double[] y, int incY);

        /// <summary>
        /// Copies the values form vector to another, from x to y.
        /// </summary>
        /// <param name="n">The order of the vectors.</param>
        /// <param name="x">A vector to copy from with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">A vector to copy to with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        void Dcopy(int n, double[] x, int incX, double[] y, int incY);

        /// <summary>
        /// Performs the operation y = alpha * x + y.
        /// </summary>
        /// <param name="n">The order of the vectors.</param>
        /// <param name="alpha">The scalar to multiply <paramref name="x"/> with.</param>
        /// <param name="x">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        void Daxpy(int n, double alpha, double[] x, int incX, double[] y, int incY);

        /// <summary>
        /// Calculates the values of a Givens rotation.
        /// </summary>
        /// <param name="a">On entry, the <paramref name="x"/> coordinate of a point. On exit, 
        /// it is the r value of a Givens rotation.</param>
        /// <param name="b">On entry, the <paramref name="y"/> coordinate of a point. On exit, 
        /// is is the z value of a Givens rotation.</param>
        /// <param name="c">On exit, it is cosine of the angle of rotation of a Givens rotation.</param>
        /// <param name="s">On exit, it is sine of the angle of rotation of a Givens rotation.</param>
        void Drotg(ref double a, ref double b, out double c, out double s);

        /// <summary>
        /// Swaps the values of one vector with another vector.
        /// </summary>
        /// <param name="n">The order of the vectors.</param>
        /// <param name="x">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        void Zswap(int n, Complex[] x, int incX, Complex[] y, int incY);

        /// <summary>
        /// Copies the values form vector to another, from x to y.
        /// </summary>
        /// <param name="n">The order of the vectors.</param>
        /// <param name="x">A vector to copy from with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">A vector to copy to with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        void Zcopy(int n, Complex[] x, int incX, Complex[] y, int incY);

        /// <summary>
        /// Performs the operation y = alpha * x + y.
        /// </summary>
        /// <param name="n">The order of the vectors.</param>
        /// <param name="alpha">The scalar to multiply <paramref name="x"/> with.</param>
        /// <param name="x">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        void Zaxpy(int n, Complex alpha, Complex[] x, int incX, Complex[] y, int incY);

        /// <summary>
        /// Calculates the values of a Givens rotation.
        /// </summary>
        /// <param name="a">On entry, the <paramref name="x"/> coordinate of a point. On exit, 
        /// it is the r value of a Givens rotation.</param>
        /// <param name="b">On entry, the <paramref name="y"/> coordinate of a point. On exit, 
        /// is is the z value of a Givens rotation.</param>
        /// <param name="c">On exit, it is cosine of the angle of rotation of a Givens rotation.</param>
        /// <param name="s">On exit, it is sine of the angle of rotation of a Givens rotation.</param>
        void Zrotg(ref Complex a, ref Complex b, out Complex c, out Complex s);

        /// <summary>
        /// Calculates the values of a modified Givens rotation.
        /// </summary>
        /// <param name="d1">The scale factor for <paramref name="x1"/>.</param>
        /// <param name="d2">The scale factor for <paramref name="y1"/>.</param>
        /// <param name="x1">The first element x(1) of the input vector.</param>
        /// <param name="y1">The second element y(1) of the input vector.</param>
        /// <param name="p">On exit, p has a length of five and contains an array defining 
        /// the type of transform matrix H constructed.</param>
        void Drotmg(ref double d1, ref double d2, ref double x1, double y1, out double[] p);

        /// <summary>
        /// Rotates points on a plane.
        /// </summary>
        /// <param name="n">The order of the vectors.</param>
        /// <param name="x">On entry, a vector containing the <paramref name="x"/> coordinates from with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).
        /// On exit, the values of <paramref name="x"/>  are over written with c*x + s*y.</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">On entry, a vector containing the <paramref name="y"/> coordinates from with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incY"/>).
        /// On exit, the values of <paramref name="y"/>  are over written with c*x - s*y.</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        /// <param name="c">The cosine of the angle of rotation.</param>
        /// <param name="s">The sine of the angle of rotation.</param>
        void Drot(int n, double[] x, int incX, double[] y, int incY, double c, double s);

        /// <summary>
        /// Rotates points on a modified plane.
        /// </summary>
        /// <param name="n">The order of the vectors.</param>
        /// <param name="x">On entry, a vector containing the <paramref name="x"/> coordinates from with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).
        /// On exit, the values of <paramref name="x"/>  are over written with H[0,0]*x[i] + H[0,1]*y[i].</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">On entry, a vector containing the <paramref name="y"/> coordinates from with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incY"/>).
        /// On exit, the values of <paramref name="x"/>  are over written with H[1,0]*x[i] + H[1,1]*y[i].</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        /// <param name="p">A vector with a length of five defining the transformation matrix H.</param>
        void Drotm(int n, double[] x, int incX, double[] y, int incY, double[] p);

        /// <summary>
        /// Rotates points on a plane.
        /// </summary>
        /// <param name="n">The order of the vectors.</param>
        /// <param name="x">On entry, a vector containing the <paramref name="x"/> coordinates from with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).
        /// On exit, the values of <paramref name="x"/>  are over written with c*x + s*y.</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">On entry, a vector containing the <paramref name="y"/> coordinates from with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incY"/>).
        /// On exit, the values of <paramref name="y"/>  are over written with c*x - s*y.</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        /// <param name="c">The cosine of the angle of rotation.</param>
        /// <param name="s">The sine of the angle of rotation.</param>
        void Zdrot(int n, Complex[] x, int incX, Complex[] y, int incY, double c, double s);

        /// <summary>
        /// Scales a vector.
        /// </summary>
        /// <param name="n">The order of the vector.</param>
        /// <param name="alpha">The scalar to scale <paramref name="x"/> by.</param>
        /// <param name="x">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        void Dscal(int n, double alpha, double[] x, int incX);

        /// <summary>
        /// Scales a vector.
        /// </summary>
        /// <param name="n">The order of the vector.</param>
        /// <param name="alpha">The scalar to scale <paramref name="x"/> by.</param>
        /// <param name="x">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        void Zscal(int n, Complex alpha, Complex[] x, int incX);

        /// <summary>
        /// Scales a vector.
        /// </summary>
        /// <param name="n">The order of the vectors.</param>
        /// <param name="alpha">The scalar to scale <paramref name="x"/> by.</param>
        /// <param name="x">A vector with a length of at least 1+(<paramref name="n"/>-1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        void Zdscal(int n, double alpha, Complex[] x, int incX);

        #endregion BLAS1 Routines

        #region BLAS2 Routines

        /// <summary>
        /// Multiplies a matrix (a) and a vector (x) and adds the result to another vector (y). y = alpha * a * x + beta * y.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="m">The number of rows of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="n">The number of columns of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="alpha">A scalar to scale <paramref name="a"/> by.</param>
        /// <param name="a">The matrix to multiply. <paramref name="a"/> must have the dimensions <paramref name="lda"/> by <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> &gt;= max(1,<paramref name="m"/>).</param>
        /// <param name="x">The vector to multiply with. If <paramref name="transA"/> == <see cref="BlasTransType.NoTrans"/>, then <b>x</b> must have a 
        /// length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>). Otherwise, <b>x</b> must have a 
        /// length of at least 1 + (<paramref name="m"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="beta">A scalar to scale <paramref name="y"/> by.</param>
        /// <param name="y">On entry, the vector to add to the result of alpha*a*x. On exit, contains
        /// the result of alpha*a*x + beta*y. If <paramref name="transA"/> == <see cref="BlasTransType.NoTrans"/>, then <b>y</b> must have a 
        /// length of at least 1 + (<paramref name="m"/> - 1)*abs(<paramref name="incY"/>). Otherwise, <b>y</b> must have a 
        /// length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        void Dgemv(BlasOrderType order, BlasTransType transA, int m, int n, double alpha, double[] a, int lda, double[] x, int incX, double beta, double[] y, int incY);

        /// <summary>
        /// Multiplies a band matrix (a) and a vector (x) and adds the result to another vector (y). y = alpha * a * x + beta * y.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="m">The number of rows of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="n">The number of columns of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="kl">The number of sub-diagonals of <paramref name="a"/>. <paramref name="kl"/>&gt;=0.</param>
        /// <param name="ku">The number of super-diagonals of <paramref name="a"/>. <paramref name="ku"/>&gt;=0.</param>
        /// <param name="alpha">A scalar to scale <paramref name="a"/> by.</param>
        /// <param name="a">The matrix to multiply. <paramref name="a"/> must have the dimensions <paramref name="lda"/> by <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> must be at least ku+kl+1.</param>
        /// <param name="x">The vector to multiply with. If <paramref name="transA"/> == <see cref="BlasTransType.NoTrans"/>, then <b>x</b> must have a 
        /// length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>). Otherwise, <b>x</b> must have a 
        /// length of at least 1 + (<paramref name="m"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="beta">A scalar to scale <paramref name="y"/> by.</param>
        /// <param name="y">On entry, the vector to add to the result of alpha*a*x. On exit, contains
        /// the result of alpha*a*x + beta*y. If <paramref name="transA"/> == <see cref="BlasTransType.NoTrans"/>, then <b>y</b> must have a 
        /// length of at least 1 + (<paramref name="m"/> - 1)*abs(<paramref name="incY"/>). Otherwise, <b>y</b> must have a 
        /// length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        void Dgbmv(BlasOrderType order, BlasTransType transA, int m, int n, int kl, int ku, double alpha, double[] a, int lda, double[] x, int incX, double beta, double[] y, int incY);

        /// <summary>
        /// Multiplies a triangular matrix (a) and a vector (x). x = a * x.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/> is an upper or lower
        /// triangular matrix.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="diag">The <see cref="BlasDiagType"/> specifying if <paramref name="a"/> is unit triangular or not.</param>
        /// <param name="n">The order of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="a">The matrix to multiply. <paramref name="a"/> must have the dimensions <paramref name="lda"/> by <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> &gt;= max(1,<paramref name="n"/>).</param>
        /// <param name="x">The vector to multiply with. <b>x</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        void Dtrmv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, double[] a, int lda, double[] x, int incX);

        /// <summary>
        /// Multiplies a triangular, band matrix (a) and a vector (x). x = a * x.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/> is an upper or lower
        /// triangular matrix.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="diag">The <see cref="BlasDiagType"/> specifying if <paramref name="a"/> is unit triangular or not.</param>
        /// <param name="n">The order of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="k">The number of super-diagonals or sub-diagonals.</param>
        /// <param name="a">The matrix to multiply. <paramref name="a"/> must have the dimensions <paramref name="lda"/> by <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> must be at least k+1.</param>
        /// <param name="x">The vector to multiply with. <b>x</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        void Dtbmv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, int k, double[] a, int lda, double[] x, int incX);

        /// <summary>
        /// Multiplies a packed triangular matrix (a) and a vector (x). x =  ap * x.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="ap"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="ap"/> is an upper or lower
        /// triangular matrix.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="ap"/>.</param>
        /// <param name="diag">The <see cref="BlasDiagType"/> specifying if <paramref name="ap"/> is unit triangular or not.</param>
        /// <param name="n">The order of <paramref name="ap"/>. Must be greater than zero.</param>
        /// <param name="ap">The matrix to multiply. The length of <paramref name="ap"/> must be at least (<paramref name="n"/>*(<paramref name="n"/> + 1))/2.</param>
        /// <param name="x">The vector to multiply with. <b>x</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        void Dtpmv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, double[] ap, double[] x, int incX);

        /// <summary>
        /// Solves a system of linear equations when a matrix (a) is a triangular matrix. Solves for x in, a * x = b
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/> is an upper or lower
        /// triangular matrix.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="diag">The <see cref="BlasDiagType"/> specifying if <paramref name="a"/> is unit triangular or not.</param>
        /// <param name="n">The order of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="a">The matrix containing the equation coefficients. <paramref name="a"/> must have the dimensions <paramref name="lda"/> by <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> &gt;= max(1,<paramref name="n"/>).</param>
        /// <param name="x">On entry, x contains the values of the b vector. On exit, x contains the solution values. <b>x</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>). </param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        void Dtrsv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, double[] a, int lda, double[] x, int incX);

        /// <summary>
        /// Solves a system of linear equations when a matrix (a) is a triangular, band matrix. Solves for x in, a * x = b
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/> is an upper or lower
        /// triangular matrix.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="diag">The <see cref="BlasDiagType"/> specifying if <paramref name="a"/> is unit triangular or not.</param>
        /// <param name="n">The order of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="k">The number of super-diagonals or sub-diagonals.</param>
        /// <param name="a">The matrix containing the equation coefficients. <paramref name="a"/> must have the dimensions <paramref name="lda"/> by <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> must be at least k+1.</param>
        /// <param name="x">On entry, x contains the values of the b vector. On exit, x contains the solution values. <b>x</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>). </param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        void Dtbsv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, int k, double[] a, int lda, double[] x, int incX);

        /// <summary>
        /// Solves a system of linear equations when a matrix (ap) is a packed triangular matrix. Solves for x in, ap * x = b
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="ap"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="ap"/> is an upper or lower
        /// triangular matrix.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="ap"/>.</param>
        /// <param name="diag">The <see cref="BlasDiagType"/> specifying if <paramref name="ap"/> is unit triangular or not.</param>
        /// <param name="n">The order of <paramref name="ap"/>. Must be greater than zero.</param>
        /// <param name="ap">The matrix containing the equation coefficients. The length of <paramref name="ap"/> must be at least (<paramref name="n"/>*(<paramref name="n"/> + 1))/2.</param>
        /// <param name="x">On entry, x contains the values of the b vector. On exit, x contains the solution values. <b>x</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>). </param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        void Dtpsv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, double[] ap, double[] x, int incX);

        /// <summary>
        /// Multiplies a matrix (a) and a vector (x) and adds the result to another vector (y). y = alpha * a * x + beta * y.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="m">The number of rows of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="n">The number of columns of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="alpha">A scalar to scale <paramref name="a"/> by.</param>
        /// <param name="a">The matrix to multiply. <paramref name="a"/> must have the dimensions <paramref name="lda"/> by <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> &gt;= max(1,<paramref name="m"/>).</param>
        /// <param name="x">The vector to multiply with. If <paramref name="transA"/> == <see cref="BlasTransType.NoTrans"/>, then <b>x</b> must have a 
        /// length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>). Otherwise, <b>x</b> must have a 
        /// length of at least 1 + (<paramref name="m"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="beta">A scalar to scale <paramref name="y"/> by.</param>
        /// <param name="y">On entry, the vector to add to the result of alpha*a*x. On exit, contains
        /// the result of alpha*a*x + beta*y. If <paramref name="transA"/> == <see cref="BlasTransType.NoTrans"/>, then <b>y</b> must have a 
        /// length of at least 1 + (<paramref name="m"/> - 1)*abs(<paramref name="incY"/>). Otherwise, <b>y</b> must have a 
        /// length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        void Zgemv(BlasOrderType order, BlasTransType transA, int m, int n, Complex alpha, Complex[] a, int lda, Complex[] x, int incX, Complex beta, Complex[] y, int incY);

        /// <summary>
        /// Multiplies a band matrix (a) and a vector (x) and adds the result to another vector (y). y = alpha * a * x + beta * y.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="m">The number of rows of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="n">The number of columns of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="kl">The number of sub-diagonals of <paramref name="a"/>. <paramref name="kl"/>&gt;=0.</param>
        /// <param name="ku">The number of super-diagonals of <paramref name="a"/>. <paramref name="ku"/>&gt;=0.</param>
        /// <param name="alpha">A scalar to scale <paramref name="a"/> by.</param>
        /// <param name="a">The matrix to multiply. <paramref name="a"/> must have the dimensions <paramref name="lda"/> by <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> must be at least ku+kl+1.</param>
        /// <param name="x">The vector to multiply with. If <paramref name="transA"/> == <see cref="BlasTransType.NoTrans"/>, then <b>x</b> must have a 
        /// length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>). Otherwise, <b>x</b> must have a 
        /// length of at least 1 + (<paramref name="m"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="beta">A scalar to scale <paramref name="y"/> by.</param>
        /// <param name="y">On entry, the vector to add to the result of alpha*a*x. On exit, contains
        /// the result of alpha*a*x + beta*y. If <paramref name="transA"/> == <see cref="BlasTransType.NoTrans"/>, then <b>y</b> must have a 
        /// length of at least 1 + (<paramref name="m"/> - 1)*abs(<paramref name="incY"/>). Otherwise, <b>y</b> must have a 
        /// length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        void Zgbmv(BlasOrderType order, BlasTransType transA, int m, int n, int kl, int ku, Complex alpha, Complex[] a, int lda, Complex[] x, int incX, Complex beta, Complex[] y, int incY);

        /// <summary>
        /// Multiplies a triangular matrix (a) and a vector (x). x = a * x.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/> is an upper or lower
        /// triangular matrix.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="diag">The <see cref="BlasDiagType"/> specifying if <paramref name="a"/> is unit triangular or not.</param>
        /// <param name="n">The order of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="a">The matrix to multiply. <paramref name="a"/> must have the dimensions <paramref name="lda"/> by <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> &gt;= max(1,<paramref name="n"/>).</param>
        /// <param name="x">The vector to multiply with. <b>x</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        void Ztrmv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, Complex[] a, int lda, Complex[] x, int incX);

        /// <summary>
        /// Multiplies a triangular, band matrix (a) and a vector (x). x = a * x.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/> is an upper or lower
        /// triangular matrix.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="diag">The <see cref="BlasDiagType"/> specifying if <paramref name="a"/> is unit triangular or not.</param>
        /// <param name="n">The order of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="k">The number of super-diagonals or sub-diagonals.</param>
        /// <param name="a">The matrix to multiply. <paramref name="a"/> must have the dimensions <paramref name="lda"/> by <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> must be at least k+1.</param>
        /// <param name="x">The vector to multiply with. <b>x</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        void Ztbmv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, int k, Complex[] a, int lda, Complex[] x, int incX);

        /// <summary>
        /// Multiplies a packed triangular matrix (a) and a vector (x). x =  ap * x.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="ap"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="ap"/> is an upper or lower
        /// triangular matrix.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="ap"/>.</param>
        /// <param name="diag">The <see cref="BlasDiagType"/> specifying if <paramref name="ap"/> is unit triangular or not.</param>
        /// <param name="n">The order of <paramref name="ap"/>. Must be greater than zero.</param>
        /// <param name="ap">The matrix to multiply. The length of <paramref name="ap"/> must be at least (<paramref name="n"/>*(<paramref name="n"/> + 1))/2.</param>
        /// <param name="x">The vector to multiply with. <b>x</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        void Ztpmv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, Complex[] ap, Complex[] x, int incX);

        /// <summary>
        /// Solves a system of linear equations when a matrix (a) is a triangular matrix. Solves for x in, a * x = b
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/> is an upper or lower
        /// triangular matrix.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="diag">The <see cref="BlasDiagType"/> specifying if <paramref name="a"/> is unit triangular or not.</param>
        /// <param name="n">The order of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="a">The matrix containing the equation coefficients. <paramref name="a"/> must have the dimensions <paramref name="lda"/> by <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> &gt;= max(1,<paramref name="n"/>).</param>
        /// <param name="x">On entry, x contains the values of the b vector. On exit, x contains the solution values. <b>x</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>). </param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        void Ztrsv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, Complex[] a, int lda, Complex[] x, int incX);

        /// <summary>
        /// Solves a system of linear equations when a matrix (a) is a triangular, band matrix. Solves for x in, a * x = b
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/> is an upper or lower
        /// triangular matrix.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="diag">The <see cref="BlasDiagType"/> specifying if <paramref name="a"/> is unit triangular or not.</param>
        /// <param name="n">The order of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="k">The number of super-diagonals or sub-diagonals.</param>
        /// <param name="a">The matrix containing the equation coefficients. <paramref name="a"/> must have the dimensions <paramref name="lda"/> by <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> must be at least k+1.</param>
        /// <param name="x">On entry, x contains the values of the b vector. On exit, x contains the solution values. <b>x</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>). </param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        void Ztbsv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, int k, Complex[] a, int lda, Complex[] x, int incX);

        /// <summary>
        /// Solves a system of linear equations when a matrix (ap) is a packed triangular matrix. Solves for x in, ap * x = b
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="ap"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="ap"/> is an upper or lower
        /// triangular matrix.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="ap"/>.</param>
        /// <param name="diag">The <see cref="BlasDiagType"/> specifying if <paramref name="ap"/> is unit triangular or not.</param>
        /// <param name="n">The order of <paramref name="ap"/>. Must be greater than zero.</param>
        /// <param name="ap">The matrix containing the equation coefficients. The length of <paramref name="ap"/> must be at least (<paramref name="n"/>*(<paramref name="n"/> + 1))/2.</param>
        /// <param name="x">On entry, x contains the values of the b vector. On exit, x contains the solution values. <b>x</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>). </param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        void Ztpsv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, Complex[] ap, Complex[] x, int incX);

        /// <summary>
        /// Multiplies a symmetric matrix (a) and a vector (x) and adds the result to another vector (y). y = alpha * a * x + beta * y.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/>'s data is stored in the upper or lower
        /// triangular part of the matrix.</param>
        /// <param name="n">The order of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="alpha">A scalar to scale <paramref name="a"/> by.</param>
        /// <param name="a">The matrix to multiply. <paramref name="a"/> must have the dimensions <paramref name="lda"/> by <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> &gt;= max(1,<paramref name="n"/>).</param>
        /// <param name="x">The vector to multiply with. <b>x</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="beta">A scalar to scale <paramref name="y"/> by.</param>
        /// <param name="y">On entry, the vector to add to the result of alpha*a*x. On exit, contains
        /// the result of alpha*a*x + beta*y. <b>y</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        void Dsymv(BlasOrderType order, BlasUpLoType uplo, int n, double alpha, double[] a, int lda, double[] x, int incX, double beta, double[] y, int incY);

        /// <summary>
        /// Multiplies a symmetric, band matrix (a) and a vector (x) and adds the result to another vector (y). y = alpha * a * x + beta * y.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/>'s data is stored in the upper or lower
        /// triangular part of the matrix.</param>
        /// <param name="n">The order of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="k">The number of super-diagonals of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="alpha">A scalar to scale <paramref name="a"/> by.</param>
        /// <param name="a">The matrix to multiply. <paramref name="a"/> must have the dimensions <paramref name="lda"/> by <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> must be at least k+1.</param>
        /// <param name="x">The vector to multiply with. <b>x</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="beta">A scalar to scale <paramref name="y"/> by.</param>
        /// <param name="y">On entry, the vector to add to the result of alpha*a*x. On exit, contains
        /// the result of alpha*a*x + beta*y. <b>y</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        void Dsbmv(BlasOrderType order, BlasUpLoType uplo, int n, int k, double alpha, double[] a, int lda, double[] x, int incX, double beta, double[] y, int incY);

        /// <summary>
        /// Multiplies a packed symmetric matrix (ap) and a vector (x) and adds the result to another vector (y). y = alpha * ap * x + beta * y.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="ap"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="ap"/>'s data is stored in the upper or lower
        /// triangular part of the matrix.</param>
        /// <param name="n">The order of <paramref name="ap"/>. Must be greater than zero.</param>
        /// <param name="alpha">A scalar to scale <paramref name="ap"/> by.</param>
        /// <param name="ap">The matrix to multiply. <paramref name="ap"/> must have a length of at least (<paramref name="n"/>*(<paramref name="n"/> + 1))/2.</param>
        /// <param name="x">The vector to multiply with. <b>x</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="beta">A scalar to scale <paramref name="y"/> by.</param>
        /// <param name="y">On entry, the vector to add to the result of alpha*ap*x. On exit, contains
        /// the result of alpha*ap*x + beta*y. <b>y</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        void Dspmv(BlasOrderType order, BlasUpLoType uplo, int n, double alpha, double[] ap, double[] x, int incX, double beta, double[] y, int incY);

        /// <summary>
        /// A rank-1 update of a general matrix. a = alpha * x * y' + a.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="m">The number of rows of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="n">The number of columns of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="alpha">A scalar to multiply the matrix created by <paramref name="x"/> and <paramref name="y"/>' with.</param>
        /// <param name="x">The vector to multiply with the transpose of <paramref name="y"/>. <b>x</b> must have a length of at least 1 + (<paramref name="m"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">The vector to multiply with <paramref name="x"/>. <b>y</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        /// <param name="a">On entry, the matrix to add to the product of <paramref name="x"/> and <paramref name="y"/>'. On exit, 
        /// it contains the result of alpha*x*y'+a.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> must be at least m.</param>
        void Dger(BlasOrderType order, int m, int n, double alpha, double[] x, int incX, double[] y, int incY, double[] a, int lda);

        /// <summary>
        /// Computes the rank-1 update of a symmetric matrix. a = alpha * x * x' + a.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/>'s data is stored in the upper or lower
        /// triangular part of the matrix.</param>
        /// <param name="n">The order of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="alpha">The scalar to multiply x*x' with.</param>
        /// <param name="x">A vector with a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="a">On entry, the matrix to add to the product of <paramref name="x"/> and <paramref name="x"/>'. On exit, 
        /// it contains the result of alpha*x*x'+a.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> must be at least n.</param>
        void Dsyr(BlasOrderType order, BlasUpLoType uplo, int n, double alpha, double[] x, int incX, double[] a, int lda);

        /// <summary>
        /// Computes the rank-1 update of a symmetric, packed matrix. ap = alpha * x * x' + ap.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="ap"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="ap"/>'s data is stored in the upper or lower
        /// triangular part of the matrix.</param>
        /// <param name="n">The order of <paramref name="ap"/>. Must be greater than zero.</param>
        /// <param name="alpha">The scalar to multiply x*x' with.</param>
        /// <param name="x">A vector with a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="ap">On entry, the matrix to add to the product of <paramref name="x"/> and <paramref name="x"/>'. On exit, 
        /// it contains the result of alpha*x*x'+ap.</param>
        void Dspr(BlasOrderType order, BlasUpLoType uplo, int n, double alpha, double[] x, int incX, double[] ap);

        /// <summary>
        /// Computes the rank-2 update of a symmetric matrix. a = alpha * x * y' + alpha *y * x' + a
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/>'s data is stored in the upper or lower
        /// triangular part of the matrix.</param>
        /// <param name="n">The order of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="alpha">The scalar to use.</param>
        /// <param name="x">A vector with a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">A vector with a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        /// <param name="a">The matrix to update. On exit, it contains the result of alpha * x * y' + alpha *y * x' + a.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> must be at least n.</param>
        void Dsyr2(BlasOrderType order, BlasUpLoType uplo, int n, double alpha, double[] x, int incX, double[] y, int incY, double[] a, int lda);

        /// <summary>
        /// Computes the rank-2 update of a symmetric, packed matrix. ap = alpha * x * y' + alpha *y * x' + ap
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="ap"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="ap"/>'s data is stored in the upper or lower
        /// triangular part of the matrix.</param>
        /// <param name="n">The order of <paramref name="ap"/>. Must be greater than zero.</param>
        /// <param name="alpha">The scalar to use.</param>
        /// <param name="x">A vector with a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">A vector with a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        /// <param name="ap">The matrix to update. It must have a length of at least (<paramref name="n"/>*(<paramref name="n"/> + 1))/2. 
        /// On exit, it contains the result of alpha * x * y' + alpha *y * x' + ap.</param>
        void Dspr2(BlasOrderType order, BlasUpLoType uplo, int n, double alpha, double[] x, int incX, double[] y, int incY, double[] ap);

        /// <summary>
        /// Multiplies a Hermitian matrix (a) and a vector (x) and adds the result to another vector (y). y = alpha * a * x + beta * y.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/>'s data is stored in the upper or lower
        /// triangular part of the matrix.</param>
        /// <param name="n">The order of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="alpha">A scalar to scale <paramref name="a"/> by.</param>
        /// <param name="a">The matrix to multiply. <paramref name="a"/> must have the dimensions <paramref name="lda"/> by <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> &gt;= max(1,<paramref name="n"/>).</param>
        /// <param name="x">A vector with a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="beta">A scalar to scale <paramref name="y"/> by.</param>
        /// <param name="y">A vector with a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        void Zhemv(BlasOrderType order, BlasUpLoType uplo, int n, Complex alpha, Complex[] a, int lda, Complex[] x, int incX, Complex beta, Complex[] y, int incY);

        /// <summary>
        /// Multiplies a Hermitian, band matrix (a) and a vector (x) and adds the result to another vector (y). y = alpha * a * x + beta * y.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/>'s data is stored in the upper or lower
        /// triangular part of the matrix.</param>
        /// <param name="n">The order of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="k">The number of super-diagonals of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="alpha">A scalar to scale <paramref name="a"/> by.</param>
        /// <param name="a">The matrix to multiply. <paramref name="a"/> must have the dimensions <paramref name="lda"/> by <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> &gt;= max(1,<paramref name="n"/>).</param>
        /// <param name="x">A vector with a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="beta">A scalar to scale <paramref name="y"/> by.</param>
        /// <param name="y">A vector with a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        void Zhbmv(BlasOrderType order, BlasUpLoType uplo, int n, int k, Complex alpha, Complex[] a, int lda, Complex[] x, int incX, Complex beta, Complex[] y, int incY);

        /// <summary>
        /// Multiplies a Hermitian, packed matrix (a) and a vector (x) and adds the result to another vector (y). y = alpha * a * x + beta * y.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="ap"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="ap"/>'s data is stored in the upper or lower
        /// triangular part of the matrix.</param>
        /// <param name="n">The order of <paramref name="ap"/>. Must be greater than zero.</param>
        /// <param name="alpha">A scalar to scale <paramref name="ap"/> by.</param>
        /// <param name="ap">The matrix to multiply. <paramref name="ap"/> must have a length of at least (<paramref name="n"/>*(<paramref name="n"/> + 1))/2.</param>
        /// <param name="x">A vector with a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="beta">A scalar to scale <paramref name="y"/> by.</param>
        /// <param name="y">A vector with a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        void Zhpmv(BlasOrderType order, BlasUpLoType uplo, int n, Complex alpha, Complex[] ap, Complex[] x, int incX, Complex beta, Complex[] y, int incY);

        /// <summary>
        /// A rank-1 update of a general matrix. a = alpha * x * y' + a.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="m">The number of rows of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="n">The number of columns of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="alpha">A scalar to multiply the matrix created by <paramref name="x"/> and <paramref name="y"/>' with.</param>
        /// <param name="x">The vector to multiply with the transpose of <paramref name="y"/>. <b>x</b> must have a length of at least 1 + (<paramref name="m"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">The vector to multiply with <paramref name="x"/>. <b>y</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        /// <param name="a">On entry, the matrix to add to the product of <paramref name="x"/> and <paramref name="y"/>'. On exit, 
        /// it contains the result of alpha*x*y'+a.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> must be at least m.</param>
        void Zgeru(BlasOrderType order, int m, int n, Complex alpha, Complex[] x, int incX, Complex[] y, int incY, Complex[] a, int lda);

        /// <summary>
        /// A rank-1 update of a general matrix. a = alpha * x * Conjugate(y') + a.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="m">The number of rows of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="n">The number of columns of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="alpha">A scalar to multiply the matrix created by <paramref name="x"/> and <paramref name="y"/>' with.</param>
        /// <param name="x">The vector to multiply with the transpose of <paramref name="y"/>. <b>x</b> must have a length of at least 1 + (<paramref name="m"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">The vector to multiply with <paramref name="x"/>. The conjugate of each value is used. <b>y</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        /// <param name="a">On entry, the matrix to add to the product of <paramref name="x"/> and <paramref name="y"/>'. On exit, 
        /// it contains the result of alpha*x*y'+a.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> must be at least m.</param>
        void Zgerc(BlasOrderType order, int m, int n, Complex alpha, Complex[] x, int incX, Complex[] y, int incY, Complex[] a, int lda);

        /// <summary>
        /// Computes the rank-1 update of a Hermitian matrix. a = alpha * x * Conjugate(x') + a.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/>'s data is stored in the upper or lower
        /// triangular part of the matrix.</param>
        /// <param name="n">The order of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="alpha">The scalar to multiply x*Conjugate(x') with.</param>
        /// <param name="x">A vector with a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="a">On entry, the matrix to add to the product of <paramref name="x"/> and <paramref name="x"/>'. On exit, 
        /// it contains the result of alpha*x*Conjugate(x')+a.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> must be at least n.</param>
        void Zher(BlasOrderType order, BlasUpLoType uplo, int n, double alpha, Complex[] x, int incX, Complex[] a, int lda);

        /// <summary>
        /// Computes the rank-1 update of a Hermitian, packed matrix. a = alpha * x * Conjugate(x') + ap.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="ap"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="ap"/>'s data is stored in the upper or lower
        /// triangular part of the matrix.</param>
        /// <param name="n">The order of <paramref name="ap"/>. Must be greater than zero.</param>
        /// <param name="alpha">The scalar to multiply x*Conjugate(x') with.</param>
        /// <param name="x">A vector with a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="ap">On entry, the matrix to add to the product of <paramref name="x"/> and <paramref name="x"/>'. It must
        /// have a length of at least (<paramref name="n"/>*(<paramref name="n"/> + 1))/2. On exit, it contains the result of alpha*x*x'+ap.</param>
        void Zhpr(BlasOrderType order, BlasUpLoType uplo, int n, double alpha, Complex[] x, int incX, Complex[] ap);

        /// <summary>
        /// Computes the rank-2 update of a Hermitian matrix. a = alpha * x * Conjugate(y') + Conjugate(alpha) * y * Conjugate(x') + a,
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="a"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/>'s data is stored in the upper or lower
        /// triangular part of the matrix.</param>
        /// <param name="n">The order of <paramref name="a"/>. Must be greater than zero.</param>
        /// <param name="alpha">The scalar to use.</param>
        /// <param name="x">A vector with a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">The vector to multiply with <paramref name="x"/>. The conjugate of each value is used. <b>y</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        /// <param name="a">The matrix to update. On exit, it contains the result of alpha * x * Conjugate(y') + Conjugate(alpha) * y * Conjugate(x') + a.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. <paramref name="lda"/> must be at least n.</param>
        void Zher2(BlasOrderType order, BlasUpLoType uplo, int n, Complex alpha, Complex[] x, int incX, Complex[] y, int incY, Complex[] a, int lda);

        /// <summary>
        /// Computes the rank-2 update of a Hermitian, packed matrix. ap = alpha * x * Conjugate(y') + Conjugate(alpha) * y * Conjugate(x') + ap,
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of <paramref name="ap"/>.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="ap"/>'s data is stored in the upper or lower
        /// triangular part of the matrix.</param>
        /// <param name="n">The order of <paramref name="ap"/>. Must be greater than zero.</param>
        /// <param name="alpha">The scalar to use.</param>
        /// <param name="x">A vector with a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incX"/>).</param>
        /// <param name="incX">The number of elements to increment the index of <paramref name="x"/> by.</param>
        /// <param name="y">The vector to multiply with <paramref name="x"/>. The conjugate of each value is used. <b>y</b> must have a length of at least 1 + (<paramref name="n"/> - 1)*abs(<paramref name="incY"/>).</param>
        /// <param name="incY">The number of elements to increment the index of <paramref name="y"/> by.</param>
        /// <param name="ap">The matrix to update. It must have a length of at least (<paramref name="n"/>*(<paramref name="n"/> + 1))/2. 
        /// On exit, it contains the result of alpha * x * Conjugate(y') + Conjugate(alpha) * y * Conjugate(x') + ap.</param>
        void Zhpr2(BlasOrderType order, BlasUpLoType uplo, int n, Complex alpha, Complex[] x, int incX, Complex[] y, int incY, Complex[] ap);

        #endregion BLAS2 Routines

        #region BLAS3 Routines

        /// <summary>
        /// Multiplies two matrices and adds the result to a third matrix. c = alpha * a * b  + beta * c, where a, b, and c are matrices.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of the matrices.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="transB">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="b"/>.</param>
        /// <param name="m">The number of rows of <paramref name="a"/> and <paramref name="c"/>. If <paramref name="a"/> has been
        /// transposed, it is the number rows after the transpose. Must be at least zero.</param>
        /// <param name="n">The number of columns of <paramref name="b"/> and <paramref name="c"/>. If <paramref name="b"/> has been
        /// transposed, it is the number columns after the transpose. Must be at least zero.</param>
        /// <param name="k">The number of columns of <paramref name="a"/> and the number of rows of <paramref name="b"/>. 
        /// If <paramref name="a"/> or <paramref name="b"/> have been transposed, it is the number of corresponding rows/columns
        /// after the matrix has been transposed. Must be at least zero.</param>
        /// <param name="alpha">A scalar to use.</param>
        /// <param name="a">One of the matrices to multiply. If <paramref name="a"/> is transposed, then <paramref name="a"/> must have the 
        /// dimensions <paramref name="lda"/> by <paramref name="m"/>, otherwise <paramref name="lda"/> by <paramref name="k"/>.
        /// </param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. If <paramref name="a"/> has been transposed, <paramref name="lda"/> 
        /// &gt;= max(1,<paramref name="k"/>), otherwise <paramref name="lda"/> &gt;= max(1,<paramref name="m"/>).</param>
        /// <param name="b">One of the matrices to multiply. If <paramref name="b"/> is transposed, then <paramref name="b"/> must have the 
        /// dimensions <paramref name="lda"/> by <paramref name="k"/>, otherwise <paramref name="lda"/> by <paramref name="n"/>.
        /// </param>
        /// <param name="ldb">The first dimension of <paramref name="b"/>. If <paramref name="b"/> has been transposed, <paramref name="ldb"/> 
        /// &gt;= max(1,<paramref name="n"/>), otherwise <paramref name="lda"/> &gt;= max(1,<paramref name="k"/>).</param>
        /// <param name="beta">A scalar to use.</param>
        /// <param name="c">The matrix to add to product of <paramref name="a"/> and <paramref name="b"/>. <paramref name="c"/> must have the
        /// dimensions <paramref name="ldc"/> by <paramref name="n"/>. On exit, it contains the result of alpha * a * b  + beta * c.
        /// </param>
        /// <param name="ldc">The first dimension of <paramref name="c"/>. <paramref name="ldc"/> &gt;= max(1,<paramref name="m"/>).</param>
        void Dgemm(BlasOrderType order, BlasTransType transA, BlasTransType transB, int m, int n, int k, double alpha, double[] a, int lda, double[] b, int ldb, double beta, double[] c, int ldc);

        /// <summary>
        /// Multiplies a symmetric matrix (a) with a matrix (b) and adds the result to a third matrix (c). c = alpha * a * b  + beta * c.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of the matrices.</param>
        /// <param name="side">The <see cref="BlasSideType"/> specifying if the multiplication should be a*b or b*a.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/>'s data is stored in the upper or lower
        /// part of the matrix.</param>
        /// <param name="m">The number of rows of <paramref name="c"/>. Must be at least zero.</param>
        /// <param name="n">The number of columns of <paramref name="c"/>. Must be at least zero.</param>
        /// <param name="alpha">A scalar to use.</param>
        /// <param name="a">A symmetric matrix. If <paramref name="side"/> == <see cref="BlasSideType.Right"/>, then <paramref name="a"/>
        /// is a <paramref name="n"/> by <paramref name="n"/> matrix with dimensions of <paramref name="lda"/> by <paramref name="n"/>.
        /// If <paramref name="side"/> == <see cref="BlasSideType.Left"/>, then <paramref name="a"/>
        /// is a <paramref name="m"/> by <paramref name="m"/> matrix with dimensions of <paramref name="lda"/> by <paramref name="m"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. If <paramref name="side"/> == <see cref="BlasSideType.Left"/>, then
        /// <paramref name="lda"/> &gt;= max(1,<paramref name="m"/>), otherwise <paramref name="lda"/> &gt;= max(1,<paramref name="n"/>).</param>
        /// <param name="b">A <paramref name="ldb"/> &gt;= max(1,<paramref name="n"/>) matrix. </param>
        /// <param name="ldb">The first dimension of <paramref name="b"/>. <paramref name="lda"/> &gt;= max(1,<paramref name="m"/>)., otherwise <paramref name="lda"/> &gt;= max(1,<paramref name="n"/>).</param>
        /// <param name="beta">A scalar to use.</param>
        /// <param name="c">The matrix to add to product of <paramref name="a"/> and <paramref name="b"/>. <paramref name="c"/> must have the
        /// dimensions <paramref name="ldc"/> by <paramref name="n"/>. On exit, it contains the result of alpha * a * b  + beta * c.</param>
        /// <param name="ldc">The first dimension of <paramref name="c"/>. <paramref name="ldc"/> &gt;= max(1,<paramref name="m"/>).</param>
        void Dsymm(BlasOrderType order, BlasSideType side, BlasUpLoType uplo, int m, int n, double alpha, double[] a, int lda, double[] b, int ldb, double beta, double[] c, int ldc);

        /// <summary>
        /// Perform an rank-n update on a symmetric matrix (c).  c = alpha * a * a' + beta * c. 
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of the matrices.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="c"/>'s data is stored in the upper or lower
        /// part of the matrix.</param>
        /// <param name="trans">If trans == <see cref="BlasTransType.NoTrans"/>, then c = alpha * a * a' + beta * c. Otherwise  c = alpha * a' * a + beta * c.</param>
        /// <param name="n">The order of <paramref name="c"/>. Must be at least zero.</param>
        /// <param name="k">If trans == <see cref="BlasTransType.NoTrans"/>, then k  is the number of columns of <paramref name="a"/>. Otherwise, k is
        /// the number of rows of <paramref name="a"/>.</param>
        /// <param name="alpha">A scalar to use.</param>
        /// <param name="a">A <paramref name="lda"/> by ka matrix, where ka == <paramref name="k"/> if <paramref name="trans"/> == <see cref="BlasTransType.NoTrans"/>, otherwise
        /// ka = <paramref name="n"/>.</param>
        /// <param name="lda">If <paramref name="trans"/> == BlasTransType.NoTrans, then lda must be at least max(1,<paramref name="n"/>). Otherwise lda must be at least max(1, <paramref name="k"/>).</param>
        /// <param name="beta">A scalar to use.</param>
        /// <param name="c">A symmetric matrix. c must have the dimensions <paramref name="ldc"/> by <paramref name="n"/>. On exit, it contains the result of alpha * a * a'  + beta * c.</param>
        /// <param name="ldc">The first dimension of <paramref name="c"/>. <paramref name="ldc"/> &gt;= max(1,<paramref name="n"/>).</param>
        void Dsyrk(BlasOrderType order, BlasUpLoType uplo, BlasTransType trans, int n, int k, double alpha, double[] a, int lda, double beta, double[] c, int ldc);

        /// <summary>
        /// Perform an rank-2k update on a symmetric matrix (c).  c = alpha * a * b' + alpha * b * a' + beta * c. 
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of the matrices.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="c"/>'s data is stored in the upper or lower
        /// part of the matrix.</param>
        /// <param name="trans">If trans == <see cref="BlasTransType.NoTrans"/>, then c = alpha * a * b' + alpha * b * a' + beta * c. 
        /// Otherwise c = alpha * a' * b + alpha * b' * a + beta * c.</param>
        /// <param name="n">The order of <paramref name="c"/>. Must be at least zero.</param>
        /// <param name="k">If trans == <see cref="BlasTransType.NoTrans"/>, then k  is the number of columns of <paramref name="a"/> and <paramref name="b"/>. Otherwise, k is
        /// the number of rows of <paramref name="a"/> and <paramref name="b"/>.</param>
        /// <param name="alpha">A scalar to use.</param>
        /// <param name="a">A <paramref name="lda"/> by ka matrix, where ka == <paramref name="k"/> if <paramref name="trans"/> == <see cref="BlasTransType.NoTrans"/>, otherwise
        /// ka = <paramref name="n"/>.</param>
        /// <param name="lda">If <paramref name="trans"/> == BlasTransType.NoTrans, then lda must be at least max(1,<paramref name="n"/>). Otherwise lda must be at least max(1, <paramref name="k"/>).</param>
        /// <param name="b">A <paramref name="ldb"/> by kb matrix, where kb == <paramref name="k"/> if <paramref name="trans"/> == <see cref="BlasTransType.NoTrans"/>, otherwise
        /// kb = <paramref name="n"/>.</param>
        /// <param name="ldb">If <paramref name="trans"/> == BlasTransType.NoTrans, then ldb must be at least max(1,<paramref name="n"/>). Otherwise ldb must be at least max(1, <paramref name="k"/>).</param>
        /// <param name="beta">A scalar to use.</param>
        /// <param name="c">A symmetric matrix. c must have the dimensions <paramref name="ldc"/> by <paramref name="n"/>. On exit, it contains the result of alpha * a * b' + alpha * b * a' + beta * c.</param>
        /// <param name="ldc">The first dimension of <paramref name="c"/>. <paramref name="ldc"/> &gt;= max(1,<paramref name="n"/>).</param>
        void Dsyr2k(BlasOrderType order, BlasUpLoType uplo, BlasTransType trans, int n, int k, double alpha, double[] a, int lda, double[] b, int ldb, double beta, double[] c, int ldc);

        /// <summary>
        /// Multiplies two matrices where one matrix (a) is a triangular matrix. b = alpha * a * b.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of the matrices.</param>
        /// <param name="side">The <see cref="BlasSideType"/> specifying if the multiplication should be a*b or b*a.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/> is an upper or lower triangular matrix.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="diag">Specifies whether <paramref name="a"/> is unit triangular.</param>
        /// <param name="m">The number of rows of <paramref name="b"/>. Must be at least zero.</param>
        /// <param name="n">The number of columns of <paramref name="b"/>. Must be at least zero.</param>
        /// <param name="alpha">A scalar to use.</param>
        /// <param name="a">A triangular matrix with dimensions <paramref name="lda"/> by k matrix, where k == <paramref name="m"/> if <paramref name="side"/> == <see cref="BlasSideType.Left"/>, otherwise
        /// k = <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. If <paramref name="side"/> == <see cref="BlasSideType.Left"/>, then
        /// <paramref name="lda"/> &gt;= max(1,<paramref name="m"/>), otherwise <paramref name="lda"/> &gt;= max(1,<paramref name="n"/>).</param>
        /// <param name="b">b must have the dimensions <paramref name="ldb"/> by <paramref name="n"/>. On exit, it contains the result of alpha * a * b.</param>
        /// <param name="ldb">The first dimension of <paramref name="b"/>. <paramref name="ldb"/> &gt;= max(1,<paramref name="m"/>).</param>
        void Dtrmm(BlasOrderType order, BlasSideType side, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int m, int n, double alpha, double[] a, int lda, double[] b, int ldb);

        /// <summary>
        /// Solve a matrix equation where one matrix (a) is a triangular matrix. a * x = alpha * b.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of the matrices.</param>
        /// <param name="side">The <see cref="BlasSideType"/> specifying if the multiplication should be a*x or x*a.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/> is an upper or lower triangular matrix.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="diag">Specifies whether <paramref name="a"/> is unit triangular.</param>
        /// <param name="m">The number of rows of <paramref name="b"/>. Must be at least zero.</param>
        /// <param name="n">The number of columns of <paramref name="b"/>. Must be at least zero.</param>
        /// <param name="alpha">A scalar to use.</param>
        /// <param name="a">A triangular matrix with dimensions <paramref name="lda"/> by k matrix, where k == <paramref name="m"/> if <paramref name="side"/> == <see cref="BlasSideType.Left"/>, otherwise
        /// k = <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. If <paramref name="side"/> == <see cref="BlasSideType.Left"/>, then
        /// <paramref name="lda"/> &gt;= max(1,<paramref name="m"/>), otherwise <paramref name="lda"/> &gt;= max(1,<paramref name="n"/>).</param>
        /// <param name="b">b must have the dimensions <paramref name="ldb"/> by <paramref name="n"/>. On exit, it contains the solution matrix x.</param>
        /// <param name="ldb">The first dimension of <paramref name="b"/>. <paramref name="ldb"/> &gt;= max(1,<paramref name="m"/>).</param>
        void Dtrsm(BlasOrderType order, BlasSideType side, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int m, int n, double alpha, double[] a, int lda, double[] b, int ldb);

        /// <summary>
        /// Multiplies two matrices and adds the result to a third matrix. c = alpha * a * b  + beta * c, where a, b, and c are matrices.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of the matrices.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="transB">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="b"/>.</param>
        /// <param name="m">The number of rows of <paramref name="a"/> and <paramref name="c"/>. If <paramref name="a"/> has been
        /// transposed, it is the number rows after the transpose. Must be at least zero.</param>
        /// <param name="n">The number of columns of <paramref name="b"/> and <paramref name="c"/>. If <paramref name="b"/> has been
        /// transposed, it is the number columns after the transpose. Must be at least zero.</param>
        /// <param name="k">The number of columns of <paramref name="a"/> and the number of rows of <paramref name="b"/>. 
        /// If <paramref name="a"/> or <paramref name="b"/> have been transposed, it is the number of corresponding rows/columns
        /// after the matrix has been transposed. Must be at least zero.</param>
        /// <param name="alpha">A scalar to use.</param>
        /// <param name="a">One of the matrices to multiply. If <paramref name="a"/> is transposed, then <paramref name="a"/> must have the 
        /// dimensions <paramref name="lda"/> by <paramref name="m"/>, otherwise <paramref name="lda"/> by <paramref name="k"/>.
        /// </param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. If <paramref name="a"/> has been transposed, <paramref name="lda"/> 
        /// &gt;= max(1,<paramref name="k"/>), otherwise <paramref name="lda"/> &gt;= max(1,<paramref name="m"/>).</param>
        /// <param name="b">One of the matrices to multiply. If <paramref name="b"/> is transposed, then <paramref name="b"/> must have the 
        /// dimensions <paramref name="lda"/> by <paramref name="k"/>, otherwise <paramref name="lda"/> by <paramref name="n"/>.
        /// </param>
        /// <param name="ldb">The first dimension of <paramref name="b"/>. If <paramref name="b"/> has been transposed, <paramref name="ldb"/> 
        /// &gt;= max(1,<paramref name="n"/>), otherwise <paramref name="lda"/> &gt;= max(1,<paramref name="k"/>).</param>
        /// <param name="beta">A scalar to use.</param>
        /// <param name="c">The matrix to add to product of <paramref name="a"/> and <paramref name="b"/>. <paramref name="c"/> must have the
        /// dimensions <paramref name="ldc"/> by <paramref name="n"/>. On exit, it contains the result of alpha * a * b  + beta * c.
        /// </param>
        /// <param name="ldc">The first dimension of <paramref name="c"/>. <paramref name="ldc"/> &gt;= max(1,<paramref name="m"/>).</param>
        void Zgemm(BlasOrderType order, BlasTransType transA, BlasTransType transB, int m, int n, int k, Complex alpha, Complex[] a, int lda, Complex[] b, int ldb, Complex beta, Complex[] c, int ldc);

        /// <summary>
        /// Multiplies a symmetric matrix (a) with a matrix (b) and adds the result to a third matrix (c). c = alpha * a * b  + beta * c.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of the matrices.</param>
        /// <param name="side">The <see cref="BlasSideType"/> specifying if the multiplication should be a*b or b*a.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/>'s data is stored in the upper or lower
        /// part of the matrix.</param>
        /// <param name="m">The number of rows of <paramref name="c"/>. Must be at least zero.</param>
        /// <param name="n">The number of columns of <paramref name="c"/>. Must be at least zero.</param>
        /// <param name="alpha">A scalar to use.</param>
        /// <param name="a">A symmetric matrix. If <paramref name="side"/> == <see cref="BlasSideType.Right"/>, then <paramref name="a"/>
        /// is a <paramref name="n"/> by <paramref name="n"/> matrix with dimensions of <paramref name="lda"/> by <paramref name="n"/>.
        /// If <paramref name="side"/> == <see cref="BlasSideType.Left"/>, then <paramref name="a"/>
        /// is a <paramref name="m"/> by <paramref name="m"/> matrix with dimensions of <paramref name="lda"/> by <paramref name="m"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. If <paramref name="side"/> == <see cref="BlasSideType.Left"/>, then
        /// <paramref name="lda"/> &gt;= max(1,<paramref name="m"/>), otherwise <paramref name="lda"/> &gt;= max(1,<paramref name="n"/>).</param>
        /// <param name="b">A <paramref name="ldb"/> &gt;= max(1,<paramref name="n"/>) matrix. </param>
        /// <param name="ldb">The first dimension of <paramref name="b"/>. <paramref name="lda"/> &gt;= max(1,<paramref name="m"/>)., otherwise <paramref name="lda"/> &gt;= max(1,<paramref name="n"/>).</param>
        /// <param name="beta">A scalar to use.</param>
        /// <param name="c">The matrix to add to product of <paramref name="a"/> and <paramref name="b"/>. <paramref name="c"/> must have the
        /// dimensions <paramref name="ldc"/> by <paramref name="n"/>. On exit, it contains the result of alpha * a * b  + beta * c.</param>
        /// <param name="ldc">The first dimension of <paramref name="c"/>. <paramref name="ldc"/> &gt;= max(1,<paramref name="m"/>).</param>
        void Zsymm(BlasOrderType order, BlasSideType side, BlasUpLoType uplo, int m, int n, Complex alpha, Complex[] a, int lda, Complex[] b, int ldb, Complex beta, Complex[] c, int ldc);

        /// <summary>
        /// Perform an rank-n update on a symmetric matrix (c).  c = alpha * a * a' + beta * c. 
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of the matrices.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="c"/>'s data is stored in the upper or lower
        /// part of the matrix.</param>
        /// <param name="trans">If trans == <see cref="BlasTransType.NoTrans"/>, then c = alpha * a * a' + beta * c. Otherwise  c = alpha * a' * a + beta * c.</param>
        /// <param name="n">The order of <paramref name="c"/>. Must be at least zero.</param>
        /// <param name="k">If trans == <see cref="BlasTransType.NoTrans"/>, then k  is the number of columns of <paramref name="a"/>. Otherwise, k is
        /// the number of rows of <paramref name="a"/>.</param>
        /// <param name="alpha">A scalar to use.</param>
        /// <param name="a">A <paramref name="lda"/> by ka matrix, where ka == <paramref name="k"/> if <paramref name="trans"/> == <see cref="BlasTransType.NoTrans"/>, otherwise
        /// ka = <paramref name="n"/>.</param>
        /// <param name="lda">If <paramref name="trans"/> == BlasTransType.NoTrans, then lda must be at least max(1,<paramref name="n"/>). Otherwise lda must be at least max(1, <paramref name="k"/>).</param>
        /// <param name="beta">A scalar to use.</param>
        /// <param name="c">A symmetric matrix. c must have the dimensions <paramref name="ldc"/> by <paramref name="n"/>. On exit, it contains the result of alpha * a * a'  + beta * c.</param>
        /// <param name="ldc">The first dimension of <paramref name="c"/>. <paramref name="ldc"/> &gt;= max(1,<paramref name="n"/>).</param>
        void Zsyrk(BlasOrderType order, BlasUpLoType uplo, BlasTransType trans, int n, int k, Complex alpha, Complex[] a, int lda, Complex beta, Complex[] c, int ldc);

        /// <summary>
        /// Perform an rank-2k update on a symmetric matrix (c).  c = alpha * a * b' + alpha * b * a' + beta * c. 
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of the matrices.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="c"/>'s data is stored in the upper or lower
        /// part of the matrix.</param>
        /// <param name="trans">If trans == <see cref="BlasTransType.NoTrans"/>, then c = alpha * a * b' + alpha * b * a' + beta * c. 
        /// Otherwise c = alpha * a' * b + alpha * b' * a + beta * c.</param>
        /// <param name="n">The order of <paramref name="c"/>. Must be at least zero.</param>
        /// <param name="k">If trans == <see cref="BlasTransType.NoTrans"/>, then k  is the number of columns of <paramref name="a"/> and <paramref name="b"/>. Otherwise, k is
        /// the number of rows of <paramref name="a"/> and <paramref name="b"/>.</param>
        /// <param name="alpha">A scalar to use.</param>
        /// <param name="a">A <paramref name="lda"/> by ka matrix, where ka == <paramref name="k"/> if <paramref name="trans"/> == <see cref="BlasTransType.NoTrans"/>, otherwise
        /// ka = <paramref name="n"/>.</param>
        /// <param name="lda">If <paramref name="trans"/> == BlasTransType.NoTrans, then lda must be at least max(1,<paramref name="n"/>). Otherwise lda must be at least max(1, <paramref name="k"/>).</param>
        /// <param name="b">A <paramref name="ldb"/> by kb matrix, where kb == <paramref name="k"/> if <paramref name="trans"/> == <see cref="BlasTransType.NoTrans"/>, otherwise
        /// kb = <paramref name="n"/>.</param>
        /// <param name="ldb">If <paramref name="trans"/> == BlasTransType.NoTrans, then ldb must be at least max(1,<paramref name="n"/>). Otherwise ldb must be at least max(1, <paramref name="k"/>).</param>
        /// <param name="beta">A scalar to use.</param>
        /// <param name="c">A symmetric matrix. c must have the dimensions <paramref name="ldc"/> by <paramref name="n"/>. On exit, it contains the result of alpha * a * b' + alpha * b * a' + beta * c.</param>
        /// <param name="ldc">The first dimension of <paramref name="c"/>. <paramref name="ldc"/> &gt;= max(1,<paramref name="n"/>).</param>
        void Zsyr2k(BlasOrderType order, BlasUpLoType uplo, BlasTransType trans, int n, int k, Complex alpha, Complex[] a, int lda, Complex[] b, int ldb, Complex beta, Complex[] c, int ldc);

        /// <summary>
        /// Multiplies two matrices where one matrix (a) is a triangular matrix. b = alpha * a * b.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of the matrices.</param>
        /// <param name="side">The <see cref="BlasSideType"/> specifying if the multiplication should be a*b or b*a.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/> is an upper or lower triangular matrix.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="diag">Specifies whether <paramref name="a"/> is unit triangular.</param>
        /// <param name="m">The number of rows of <paramref name="b"/>. Must be at least zero.</param>
        /// <param name="n">The number of columns of <paramref name="b"/>. Must be at least zero.</param>
        /// <param name="alpha">A scalar to use.</param>
        /// <param name="a">A triangular matrix with dimensions <paramref name="lda"/> by k matrix, where k == <paramref name="m"/> if <paramref name="side"/> == <see cref="BlasSideType.Left"/>, otherwise
        /// k = <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. If <paramref name="side"/> == <see cref="BlasSideType.Left"/>, then
        /// <paramref name="lda"/> &gt;= max(1,<paramref name="m"/>), otherwise <paramref name="lda"/> &gt;= max(1,<paramref name="n"/>).</param>
        /// <param name="b">b must have the dimensions <paramref name="ldb"/> by <paramref name="n"/>. On exit, it contains the result of alpha * a * b.</param>
        /// <param name="ldb">The first dimension of <paramref name="b"/>. <paramref name="ldb"/> &gt;= max(1,<paramref name="m"/>).</param>
        void Ztrmm(BlasOrderType order, BlasSideType side, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int m, int n, Complex alpha, Complex[] a, int lda, Complex[] b, int ldb);

        /// <summary>
        /// Solve a matrix equation where one matrix (a) is a triangular matrix. a * x = alpha * b.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of the matrices.</param>
        /// <param name="side">The <see cref="BlasSideType"/> specifying if the multiplication should be a*x or x*a.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/> is an upper or lower triangular matrix.</param>
        /// <param name="transA">The <see cref="BlasTransType"/> specifying whether and how to transpose <paramref name="a"/>.</param>
        /// <param name="diag">Specifies whether <paramref name="a"/> is unit triangular.</param>
        /// <param name="m">The number of rows of <paramref name="b"/>. Must be at least zero.</param>
        /// <param name="n">The number of columns of <paramref name="b"/>. Must be at least zero.</param>
        /// <param name="alpha">A scalar to use.</param>
        /// <param name="a">A triangular matrix with dimensions <paramref name="lda"/> by k matrix, where k == <paramref name="m"/> if <paramref name="side"/> == <see cref="BlasSideType.Left"/>, otherwise
        /// k = <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. If <paramref name="side"/> == <see cref="BlasSideType.Left"/>, then
        /// <paramref name="lda"/> &gt;= max(1,<paramref name="m"/>), otherwise <paramref name="lda"/> &gt;= max(1,<paramref name="n"/>).</param>
        /// <param name="b">b must have the dimensions <paramref name="ldb"/> by <paramref name="n"/>. On exit, it contains the solution matrix x.</param>
        /// <param name="ldb">The first dimension of <paramref name="b"/>. <paramref name="ldb"/> &gt;= max(1,<paramref name="m"/>).</param>
        void Ztrsm(BlasOrderType order, BlasSideType side, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int m, int n, Complex alpha, Complex[] a, int lda, Complex[] b, int ldb);

        /// <summary>
        /// Multiplies two matrices, where one of the matrices (a) is a Hermitian matrix, and adds the result to a third matrix. c = alpha * a * b  + beta * c.
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of the matrices.</param>
        /// <param name="side">The <see cref="BlasSideType"/> specifying if the multiplication should be a*b or b*a.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="a"/>'s data is stored in the upper or lower
        /// part of the matrix.</param>
        /// <param name="m">The number of rows of <paramref name="c"/>. Must be at least zero.</param>
        /// <param name="n">The number of columns of <paramref name="c"/>. Must be at least zero.</param>
        /// <param name="alpha">A scalar to use.</param>
        /// <param name="a">A Hermitian matrix with dimensions <paramref name="lda"/> by k matrix, where k == <paramref name="m"/> if <paramref name="side"/> == <see cref="BlasSideType.Left"/>, otherwise
        /// k = <paramref name="n"/>.</param>
        /// <param name="lda">The first dimension of <paramref name="a"/>. If <paramref name="side"/> == <see cref="BlasSideType.Left"/>, then
        /// <paramref name="lda"/> &gt;= max(1,<paramref name="m"/>), otherwise <paramref name="lda"/> &gt;= max(1,<paramref name="n"/>).</param>
        /// <param name="b">b must have the dimensions <paramref name="ldb"/> by <paramref name="n"/>. On exit, it contains the result of alpha * a * b.</param>
        /// <param name="ldb">The first dimension of <paramref name="b"/>. <paramref name="ldb"/> &gt;= max(1,<paramref name="m"/>).</param>
        /// <param name="beta">A scalar to use.</param>
        /// <param name="c">The matrix to add to product of <paramref name="a"/> and <paramref name="b"/>. <paramref name="c"/> must have the
        /// dimensions <paramref name="ldc"/> by <paramref name="n"/>. On exit, it contains the result of alpha * a * b  + beta * c.</param>
        /// <param name="ldc">The first dimension of <paramref name="c"/>. <paramref name="ldc"/> &gt;= max(1,<paramref name="m"/>).</param>
        void Zhemm(BlasOrderType order, BlasSideType side, BlasUpLoType uplo, int m, int n, Complex alpha, Complex[] a, int lda, Complex[] b, int ldb, Complex beta, Complex[] c, int ldc);

        /// <summary>
        /// Perform an rank-n update on a Hermitian matrix (c).  c = alpha * a * Conjugate(a') + beta * c. 
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of the matrices.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="c"/>'s data is stored in the upper or lower
        /// part of the matrix.</param>
        /// <param name="trans">If trans == <see cref="BlasTransType.NoTrans"/>, then c = alpha * a * Conjugate(a') + beta * c. Otherwise  c = alpha * Conjugate(a') * a + beta * c.</param>
        /// <param name="n">The order of <paramref name="c"/>. Must be at least zero.</param>
        /// <param name="k">If trans == <see cref="BlasTransType.NoTrans"/>, then k is the number of columns of <paramref name="a"/>. Otherwise, k is
        /// the number of rows of <paramref name="a"/>.</param>
        /// <param name="alpha">A scalar to use.</param>
        /// <param name="a">A <paramref name="lda"/> by ka matrix, where ka == <paramref name="k"/> if <paramref name="trans"/> == <see cref="BlasTransType.NoTrans"/>, otherwise
        /// ka = <paramref name="n"/>.</param>
        /// <param name="lda">If <paramref name="trans"/> == BlasTransType.NoTrans, then lda must be at least max(1,<paramref name="n"/>). Otherwise lda must be at least max(1, <paramref name="k"/>).</param>
        /// <param name="beta">A scalar to use.</param>
        /// <param name="c">A Hermitian matrix. c must have the dimensions <paramref name="ldc"/> by <paramref name="n"/>. On exit, it contains the result of alpha * a * Conjugate(a')  + beta * c.</param>
        /// <param name="ldc">The first dimension of <paramref name="c"/>. <paramref name="ldc"/> &gt;= max(1,<paramref name="n"/>).</param>
        void Zherk(BlasOrderType order, BlasUpLoType uplo, BlasTransType trans, int n, int k, double alpha, Complex[] a, int lda, double beta, Complex[] c, int ldc);

        /// <summary>
        /// Perform an rank-2k update on a Hermitian matrix (c).  c = alpha * a * Conjugate(b') + Conjugate(alpha) * b * Conjugate(a') + beta * c. 
        /// </summary>
        /// <param name="order">The <see cref="BlasOrderType"/> specifying the column order of the matrices.</param>
        /// <param name="uplo">The <see cref="BlasUpLoType"/> specifying if <paramref name="c"/>'s data is stored in the upper or lower
        /// part of the matrix.</param>
        /// <param name="trans">If trans == <see cref="BlasTransType.NoTrans"/>, then c = alpha * a * Conjugate(b') + Conjugate(alpha) * b * Conjugate(a') + beta * c. 
        /// Otherwise c = alpha * Conjugate(b') * a + Conjugate(alpha) * Conjugate(a') * b + beta * c.</param>
        /// <param name="n">The order of <paramref name="c"/>. Must be at least zero.</param>
        /// <param name="k">If trans == <see cref="BlasTransType.NoTrans"/>, then k  is the number of columns of <paramref name="a"/> and <paramref name="b"/>. Otherwise, k is
        /// the number of rows of <paramref name="a"/> and <paramref name="b"/>.</param>
        /// <param name="alpha">A scalar to use.</param>
        /// <param name="a">A <paramref name="lda"/> by ka matrix, where ka == <paramref name="k"/> if <paramref name="trans"/> == <see cref="BlasTransType.NoTrans"/>, otherwise
        /// ka = <paramref name="n"/>.</param>
        /// <param name="lda">If <paramref name="trans"/> == BlasTransType.NoTrans, then lda must be at least max(1,<paramref name="n"/>). Otherwise lda must be at least max(1, <paramref name="k"/>).</param>
        /// <param name="b">A <paramref name="ldb"/> by kb matrix, where kb == <paramref name="k"/> if <paramref name="trans"/> == <see cref="BlasTransType.NoTrans"/>, otherwise
        /// kb = <paramref name="n"/>.</param>
        /// <param name="ldb">If <paramref name="trans"/> == BlasTransType.NoTrans, then ldb must be at least max(1,<paramref name="n"/>). Otherwise ldb must be at least max(1, <paramref name="k"/>).</param>
        /// <param name="beta">A scalar to use.</param>
        /// <param name="c">A symmetric matrix. c must have the dimensions <paramref name="ldc"/> by <paramref name="n"/>. On exit, it contains the result of alpha * a * Conjugate(b') + Conjugate(alpha) * b * Conjugate(a') + beta * c.</param>
        /// <param name="ldc">The first dimension of <paramref name="c"/>. <paramref name="ldc"/> &gt;= max(1,<paramref name="n"/>).</param>
        void Zher2k(BlasOrderType order, BlasUpLoType uplo, BlasTransType trans, int n, int k, Complex alpha, Complex[] a, int lda, Complex[] b, int ldb, double beta, Complex[] c, int ldc);

        #endregion BLAS3 Routines
    }
}
